#include <stdio.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>

#define	FIFO_PATH0	"fifo_file0"
#define	FIFO_PATH1	"fifo_file1"
#define	BUF_SIZE	256


int g_stop = 0;

void sig_pipe(int signum)
{
	if(SIGPIPE == signum)
	{
		printf("get pipe broken signal and let programe exit\n");
		g_stop = 1;
	}
}

void print_usage(char *argv)
{
	printf("Usage:  %s [0/1]\n", argv) ;
    printf("        One process \"%s 0\"\n", argv) ;
    printf("        Other process \"%s 1\"\n", argv) ;
    printf("        process %s 0 can chat with %s 1\n", argv, argv) ;
	return ;
}


int main(int argc, char **argv)
{
	int	fifo_fdr, fifo_fdw ;
	char	*path_name = NULL ;
	int	mode ;
	fd_set	rset;
	char	rbuf[BUF_SIZE] ;
	int	rv ;
	time_t	ticks ;

	path_name = basename(argv[0]) ;
    if(argv[1] == NULL) 
    {
        print_usage(path_name);
        return 0 ;
    }
	mode = atoi(argv[1]) ;
    printf("running in here\n");
	if( argc != 2 )
	{
		print_usage(path_name) ;
		return 0 ;
	}
	if(mode != 0 && mode != 1)
	{
		print_usage(path_name) ;
		return 0 ;
	}


	if( access(FIFO_PATH0, F_OK) != 0)//F_OK tests for the existence of the file
	{
		if( mkfifo( FIFO_PATH0, 0666) < 0)
		{
			printf("mkfifo() failure: %s\n", strerror(errno)) ;
			return -1 ;
		}
		printf("Create %s sucessful!\n", FIFO_PATH0) ;
	}

	if( access(FIFO_PATH1, F_OK) != 0)//F_OK tests for the existence of the file
	{	
		if( mkfifo( FIFO_PATH1,0666) < 0)
		{
			printf("mkfifo() failure: %s\n", strerror(errno)) ;
			return -1 ;
		}
		printf("Create %s sucessful!\n", FIFO_PATH1) ;
	}
	signal(SIGPIPE, sig_pipe);


	if(mode == 0)//mode[0] open FIFO_PATH0 for read, FIFO_PATH1 for write
	{
		printf("Mode[%d] is running...\n", mode) ;	
		fifo_fdr = open(FIFO_PATH0, O_RDONLY) ;
		fifo_fdw = open(FIFO_PATH1, O_WRONLY) ;
		if(fifo_fdr < 0 || fifo_fdw < 0)
		{
			printf("Model[%d] process open %s or %s failure: %s\n",mode ,FIFO_PATH0, FIFO_PATH1, strerror(errno)) ;
			goto cleanup ;
		}
		printf("Model[%d] open fifo sucessful!\n", mode) ;
	
	}

	else //mode[1] open FIFO_PATH0 for write, FIFO_PATH1 for read
	{	
		printf("Mode[%d] is running...\n", mode) ;	
		fifo_fdw = open(FIFO_PATH0, O_WRONLY) ;
		fifo_fdr = open(FIFO_PATH1, O_RDONLY) ;
		if(fifo_fdr < 0 || fifo_fdw < 0)
		{
			printf("Model[%d] open %s or %s failure: %s\n",mode ,FIFO_PATH0, FIFO_PATH1, strerror(errno)) ;
			goto cleanup ;
		}
		printf("Model[%d] open fifo sucessful!\n", mode) ;
	
	}

	printf("start chating with another program now, please input message now: \n");
	while(!g_stop)
	{
		FD_ZERO(&rset) ;
		FD_SET(STDIN_FILENO, &rset) ;
		FD_SET(fifo_fdr, &rset) ;
		rv = select(fifo_fdr+1, &rset, NULL, NULL, NULL) ;
		if(rv < 0)
		{
			printf("select() failed: %s\n", strerror(errno)) ;
			goto cleanup ;
		}
		if(rv == 0)
		{
			printf("select() time out!\n") ;
			goto cleanup ;
		}

		ticks = time(NULL) ;

		if( FD_ISSET(STDIN_FILENO, &rset) )
		{
			memset(rbuf, 0, sizeof(rbuf)) ;
			fgets(rbuf, sizeof(rbuf), stdin) ;
			if( write(fifo_fdw, rbuf, strlen(rbuf)) < 0)
			{
				printf("write to other side failure :%s\n", strerror(errno)) ;
				break ;
			}

		}

		if( FD_ISSET(fifo_fdr, &rset) )
		{
			memset(rbuf, 0, sizeof(rbuf)) ;
			rv = read(fifo_fdr, rbuf, sizeof(rbuf)) ;
			if(rv < 0)
			{
				printf("read() error: %s\n", strerror(errno)) ;
				break ;
			}
			if(rv ==0 )
			{
				printf("FIFO side of write close, process will exit...\n") ;
				break ;
			}
			
			printf("%.24s\n",ctime(&ticks)) ;
			printf("	<-- %s", rbuf) ;
		}

	}


cleanup:
	close(fifo_fdr) ;
	close(fifo_fdw) ;

	return 0 ;
}
